import logging
import os
import shutil

import re
from django.core.management.base import BaseCommand
from django.db import connection

logger = logging.getLogger(__name__)
from application.settings import BASE_DIR


class Command(BaseCommand):
    """
    创建App命令:
    python manage.py createapp app名
    python manage.py createapp app01 app02 ...
    python manage.py createapp 一级文件名/app01 ...    # 支持多级目录建app
    """

    def add_arguments(self, parser):
        parser.add_argument('app_name', nargs='*', type=str, )

    def handle(self, *args, **options):
        app_name = options.get('app_name')
        for name in app_name:
            print(f"开始创建app")
            names = name.split('/')
            dnames = ".".join(names)
            Appclass=name.capitalize()
            app_path = os.path.join(BASE_DIR, "apps", *names)
             # 判断app是否存在
            if os.path.exists(app_path):
                print(f"创建失败，App {name} 已存在！")
                break
            #生成前端文件
            Webpath=os.path.abspath(os.path.join(BASE_DIR, "../web"))
            apifolder=os.path.join(Webpath, "src","api",name)
            Sapifile = os.path.join(Webpath, "src","template",'appname.js')            
            Tapifile = os.path.join(Webpath, "src","api",name,'appname.js')
            viewsfolder=os.path.join(Webpath, "src","views",name)
            Sviewfile = os.path.join(Webpath, "src","template",'appname.vue')            
            Tviewfile = os.path.join(Webpath, "src","views",name,'appname.vue')
             # 判断api是否存在
            if os.path.exists(apifolder):
                print(f"创建{name} api，已存在！")
                break
            else:
                os.makedirs(apifolder)
                shutil.copyfile(Sapifile,Tapifile)
                with open(Tapifile, 'r', encoding='UTF-8') as f:                
                    alllines=f.readlines()
                    f.close()
                with open(Tapifile, 'w', encoding='UTF-8') as f:
                    for eachline in alllines:
                        a=re.sub('appname',name,eachline)
                        a=re.sub('Appclass',Appclass,a)                        
                        f.writelines(a)
                    f.close()
                os.rename(Tapifile,os.path.join(Webpath, "src","api",name,name+'.js'))


             # 判断views是否存在
            if os.path.exists(viewsfolder):
                print(f"创建{name} views，已存在！")
                break
            else:
                os.makedirs(viewsfolder)
                shutil.copyfile(Sviewfile,Tviewfile)
                with open(Tviewfile, 'r', encoding='UTF-8') as f:                
                    alllines=f.readlines()
                    f.close()
                with open(Tviewfile, 'w', encoding='UTF-8') as f:
                    for eachline in alllines:
                        a=re.sub('appname',name,eachline)
                        a=re.sub('Appname',Appclass,a)                        
                        f.writelines(a)
                    f.close()
                os.rename(Tviewfile,os.path.join(Webpath, "src","views",name,name+'.vue'))


            source_path = os.path.join(BASE_DIR, "apps", "vadmin", "template")
            target_path = app_path
            if not os.path.exists(target_path):
                # 如果目标路径不存在原文件夹的话就创建
                os.makedirs(target_path)
            if os.path.exists(source_path):
                # 如果目标路径存在原文件夹的话就先删除
                shutil.rmtree(target_path)
            shutil.copytree(source_path, target_path)
            # 修改app中的apps 内容
            content = f"""from django.apps import AppConfig


class {name.capitalize()}Config(AppConfig):
    name = 'apps.{dnames}'
    verbose_name = "{name}App"
"""
            with open(os.path.join(app_path, "apps.py"), 'w', encoding='UTF-8') as f:
                f.write(content)
                f.close()            
            
            with open(os.path.join(app_path, "filters.py"), 'r', encoding='UTF-8') as f:                
                alllines=f.readlines()
                f.close()
            with open(os.path.join(app_path, "filters.py"), 'w', encoding='UTF-8') as f:
                for eachline in alllines:
                    a=re.sub('appname',name,eachline)
                    a=re.sub('Appclass',Appclass,a)
                    f.writelines(a)
                f.close()
            with open(os.path.join(app_path, "serializers.py"), 'r', encoding='UTF-8') as f:                
                alllines=f.readlines()
                f.close()
            with open(os.path.join(app_path, "serializers.py"), 'w', encoding='UTF-8') as f:
                for eachline in alllines:
                    a=re.sub('appname',name,eachline)
                    a=re.sub('Appclass',Appclass,a)
                    f.writelines(a)
                f.close()
            with open(os.path.join(app_path, "urls.py"), 'r', encoding='UTF-8') as f:                
                alllines=f.readlines()
                f.close()
            with open(os.path.join(app_path, "urls.py"), 'w', encoding='UTF-8') as f:
                for eachline in alllines:
                    a=re.sub('appname',name,eachline)
                    a=re.sub('Appclass',Appclass,a)
                    f.writelines(a)
                f.close()
            with open(os.path.join(app_path, "views.py"), 'r', encoding='UTF-8') as f:                
                alllines=f.readlines()
                f.close()
            with open(os.path.join(app_path, "views.py"), 'w', encoding='UTF-8') as f:
                for eachline in alllines:
                    a=re.sub('appname',name,eachline)
                    a=re.sub('Appclass',Appclass,a)
                    f.writelines(a)
                f.close()
            with open(os.path.join(app_path, "models","__init__.py"), 'r', encoding='UTF-8') as f:                
                alllines=f.readlines()
                f.close()
            with open(os.path.join(app_path, "models","__init__.py"), 'w', encoding='UTF-8') as f:
                for eachline in alllines:
                    a=re.sub('appname',name,eachline)
                    a=re.sub('Appclass',Appclass,a)
                    f.writelines(a)
                f.close()
            with open(os.path.join(app_path, "models","appname.py"), 'r', encoding='UTF-8') as f:                
                alllines=f.readlines()
                f.close()
            with open(os.path.join(app_path, "models","appname.py"), 'w', encoding='UTF-8') as f:
                for eachline in alllines:
                    a=re.sub('appname',name,eachline)
                    a=re.sub('Appclass',Appclass,a)
                    f.writelines(a)
                f.close()
            os.rename(os.path.join(app_path, "models","appname.py"),os.path.join(app_path, "models",name+".py"))

            # 注册app到 settings.py 中
            injection(os.path.join(BASE_DIR, "application", "settings.py"), f"    'apps.{dnames}',\n", "INSTALLED_APPS",
                      "]")

            # 注册app到 urls.py 中
            injection(os.path.join(BASE_DIR, "application", "urls.py"),
                      f"    re_path(r'^{name}/', include('apps.{dnames}.urls')),\n", "urlpatterns = [",
                      "]")

            print(f"后台创建 {name} App成功")

            print(f"添加菜单")
            #添加菜单
            #INSERT ( `modifier`,  `dept_belong_id`,  `update_datetime`,  `create_datetime`,  `menuType`,  `icon`,  `name`,  `orderNum`,  `isFrame`,  `web_path`,  `component_path`,  `interface_path`,  `interface_method`,  `perms`,  `status`,  `visible`,  `isCache`,  `creator_id`,  `parentId_id`) VALUES() INTO permission_menu
            with connection.cursor() as cur:
                mlsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 0,'build','{name}',6,1,'/{name}','','','GET','',1,1,1,1,0) """
                cur.execute(mlsql)
                fid=cur.lastrowid
                menusql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 1,'build','{name}',1,1,'{name}','{name}/{name}','','GET','',1,1,1,1,{fid}) """
                cur.execute(menusql)
                mid=cur.lastrowid
                selectsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','查询',1,1,'','','/{name}/{name}/','GET','{name}:{name}:get',1,1,1,1,{mid}) """
                cur.execute(selectsql)
                addsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','添加',2,1,'','','/{name}/{name}/','POST','{name}:{name}:post',1,1,1,1,{mid}) """
                cur.execute(addsql)
                idid="{id}"
                updatesql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','修改',3,1,'','','/{name}/{name}/{idid}/','PUT','{name}:{name}:{idid}:put',1,1,1,1,{mid}) """
                cur.execute(updatesql)
                delsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','删除',4,1,'','','/{name}/{name}/{idid}/','DELETE','{name}:{name}:{idid}:delete',1,1,1,1,{mid}) """
                cur.execute(delsql)
                exportsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','导出',5,1,'','','/{name}/{name}/export/','GET','{name}:{name}:export:get',1,1,1,1,{mid}) """
                cur.execute(exportsql)
                selectsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','导入',6,1,'','','/{name}/{name}/importTemplate/','GET','{name}:{name}:importTemplate:get',1,1,1,1,{mid}) """
                cur.execute(selectsql)
                addsql=f"""INSERT INTO permission_menu (modifier,  dept_belong_id,  menuType,  icon,  name,  orderNum,  isFrame,  web_path,  component_path,  interface_path,  interface_method,  perms,  status,  visible,  isCache,  creator_id,  parentId_id) 
 VALUES('admin', 1, 2,'','导入',7,1,'','','/{name}/{name}/importTemplate/','POST','{name}:{name}:importTemplate:post',1,1,1,1,{mid}) """
                cur.execute(addsql)

            print(f"{name} 菜单添加成功")
                
                




def injection(file_path, insert_content, startswith, endswith):
    with open(file_path, "r+", encoding="utf-8") as f:
        data = f.readlines()
        with open(file_path, 'w', encoding='UTF-8') as f1:
            is_INSTALLED_APPS = False
            is_insert = False
            for content in data:
                # 判断文件是否 INSTALLED_APPS 开头
                if not is_insert and content.startswith(startswith):
                    is_INSTALLED_APPS = True
                if not is_insert and content.startswith(endswith) and is_INSTALLED_APPS:
                    # 给前一行插入数据
                    content = insert_content + content
                    is_insert = True
                f1.writelines(content)
